package com.cloud.rou.im.protocol.serialize;


import com.cloud.rou.im.core.util.IOUtil;
import com.cloud.rou.im.core.util.ObjectNullUtil;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.util.Pool;

import java.io.ByteArrayOutputStream;

/**
 *
 * @author GaoShuangWen
 */
@BindAndEnableSerializer(name = SerializeTypeConstants.KRYO)
public class KryoSerializer implements Serializer {

    private static Pool<Kryo> kryoPool = new Pool<Kryo>(true, false, 8) {
        @Override
        protected Kryo create() {
            Kryo kryo = new Kryo();
            kryo.setRegistrationRequired(false);
            kryo.setReferences(true);
            return kryo;
        }
    };

    private static Pool<Output> outputPool = new Pool<Output>(true, false, 16) {
        @Override
        protected Output create() {
            return new Output(1024, -1);
        }
    };

    private static Pool<Input> inputPool = new Pool<Input>(true, false, 16) {
        @Override
        protected Input create() {
            return new Input(1024);
        }
    };
    

    private KryoSerializer() {

    }

    @Override
    public byte[] serialize(Object object) {
        ObjectNullUtil.notNull(object);
        byte[] bytes = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Kryo kryo = kryoPool.obtain();
        Output output = outputPool.obtain();
        try {
            output.setOutputStream(outputStream);
            kryo.writeClassAndObject(output, object);
            output.flush();
            bytes = outputStream.toByteArray();
        } catch (Exception e) {
           
        } finally {
            IOUtil.close(outputStream);
            kryoPool.free(kryo);
            outputPool.free(output);
        }
        return bytes;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T deserialize(byte[] bytes, Class<T> clazz) {
        ObjectNullUtil.notNull(bytes);
        T object = null;
        Kryo kryo = kryoPool.obtain();
        Input input = inputPool.obtain();
        try {
            input.setBuffer(bytes);
            object = (T) kryo.readClassAndObject(input);
        } catch (Exception e) {
            
        } finally {
            kryoPool.free(kryo);
            inputPool.free(input);
        }
        return object;
    }


}
